#!/usr/bin/env python

# KiriKiri .XP3 archive index extraction tool
#
#   Extracts an .XP3 archive index to a file. Used to study
# the format of NekoPara XP3 archives' indexes. End users
# have no real use for this.
#
# Last modified 28/02/2016 by SmilingWolf

import sys, os, zlib, binascii
from array import array
from cStringIO import StringIO
from insani import *

if len(sys.argv) != 3:
   print 'Please give an XP3 archive filename and a desired output file on the\ncommand line.'
   sys.exit(0)

arcfile = open(sys.argv[1], 'rb')
filesize = os.stat(sys.argv[1]).st_size

# Read header and index structure
assert_string(arcfile, 'XP3\x0D\x0A\x20\x0A\x1A\x8B\x67\x01', ERROR_ABORT)
indexoffset = read_unsigned(arcfile, LONG_LENGTH)
assert indexoffset < filesize
arcfile.seek(indexoffset)

# To keep compatibility with legacy xp3 files we check if the current byte is 0x80
# This is a constant defined inside KiriKiriZ itself.
indexcontinue = arcfile.read(1)
arcfile.seek(-1, 1)
if indexcontinue == '\x80':
    arcfile.seek(9, 1)
    indexoffset = read_unsigned(arcfile, LONG_LENGTH)
    arcfile.seek(indexoffset)

assert_string(arcfile, '\x01', ERROR_WARNING)
compsize = read_unsigned(arcfile, LONG_LENGTH)
origsize = read_unsigned(arcfile, LONG_LENGTH)
print 'indexoffset:', hex(indexoffset)
print 'compsize:', hex(compsize)
assert indexoffset + compsize + 17 == filesize
uncompressed = arcfile.read(compsize).decode('zlib')
assert len(uncompressed) == origsize
indexbuffer = StringIO(uncompressed)

outfile = open(sys.argv[2],'wb')
outfile.write(indexbuffer.getvalue())
outfile.close()

indexbuffer.close()
arcfile.close()
